import { PROJECTNAME, CVERSION, CHANNEL, requestList } from '../globalData'
import { showLoading, hideLoading, showToast } from '../handlers'
import { str2EncodeByDES, decodeByDES } from '../tripledes'
import { postLogin } from "./postLogin";

const globalData = getApp().globalData;
const loginPromise = globalData.loginPromise;

/**
 * @author Dom
 * @param url, type: string
 * state: 请求的链接
 * @return: undefined
 * @description: 添加url到requestList
 */
function addRequestList(url) {
    requestList.push(url)
}

/**
 * @author Dom
 * @param url, type: string
 * state: 请求的链接
 * @return: undefined
 * @description: 从requestList清除对应的url，并通过requestList的长度，决定是否调用hideLoading方法。
 */
function deleteRequestList(url) {
    let index = requestList.findIndex(item => item === url);
    if (index === -1) return;
    requestList.splice(index, 1);
    if (requestList.length === 0) {
        requestWrapper.defaultParams.isShowingLoading = false;
        hideLoading()
    }
}

/**
 * @author Dom
 * @param params, type: object
 * state: 配置请求使用的对象, { isEncode: true, loading: true, ...wxRequestObject }
 * wxRequestObject的字段参照, https://developers.weixin.qq.com/miniprogram/dev/api/wx.request.html , wx.request传递的参数对象。
 * 会默认添加登录之后的sessionId在header中
 * @param data, type: object
 * state: 请求数据, { channel: 渠道号, cversion: 版本号, pdata: { smartUserId: 用户ID, ...data }  }
 * 会默认添加渠道号和版本号, 由 ./globalData.js 统一控制。
 * 登录接口仅在 app.js 进行调用( postLogin(...) )
 * 登录成功之后, 会默认在pdata中调用 smartUserId。
 * @return: undefined
 * @description: 统一请求对象, 经过处理之后, 再调用 wx.request() 。
 */
function requestWrapper(params, data) {
    loginPromise.then(loginInfoFromResolve => {
        // merge default
        params = Object.assign({}, requestWrapper.defaultParams, params);

        params.url = params.url.indexOf(PROJECTNAME) === -1 ? params.url : params.url.slice(PROJECTNAME.length);
        params.url = params.url.indexOf('http') === -1 ? PROJECTNAME + params.url : params.url;
        params.header = Object.assign({
            sessionId: globalData.loginInfo.sessionId
        }, requestWrapper.defaultParams.header, params.header);

        //enCode data
        let sourceData = {
            smartUserId: globalData.loginInfo.loginedUser.userId,
            ...data
        };
        console.log(params.url);
        if (params.isEnCode) {
            let sdt = str2EncodeByDES(sourceData, globalData.loginInfo.key);
            if (params.isMergeDefaultData) {
                data = Object.assign({}, requestWrapper.defaultData, {
                    pdata: null,
                    sdt
                });
            } else {
                data = { sdt }
            }
        } else {
            if (params.isMergeDefaultData) {
                data = Object.assign({}, requestWrapper.defaultData, {
                    pdata: sourceData
                });
            } else {
                data = { ...sourceData }
            }
        }
        params.data = data;

        if (params.loading) {
            addRequestList(params.url);
            if (!params.isShowingLoading) {
                requestWrapper.defaultParams.isShowingLoading = true;
                showLoading() //handle hide on function deleteRequestList
            }
        }

        wx.request({
            ...params,
            success: res => {
                const { statusCode } = res;
                // if(statusCode === 404){
                    // const error404 = new Error('404 link');
                    // throw error404;
                    // return
                // }
                const resultRaw = JSON.parse(JSON.stringify(res.data));
                const dataWrapper = res.data;
                const { code, msg, data, srs } = dataWrapper;
                if (code === 101001) {
                    requestWrapper.handleLogTimeout();
                    return
                }
                if (srs && !data) {
                    const decodedData = decodeByDES(srs);
                    if (typeof decodedData === 'string') {
                        res.data.data = JSON.parse(decodedData)
                    } else {
                        res.data.data = decodedData
                    }
                }
                console.log(`success: ${params.url}`);
                console.log(`未加密data, ${params.isEnCode ? '需要加密' : '无需加密'}:`);
                console.log(sourceData);
                console.log('result raw:');
                console.log(resultRaw);
                console.log('result real:');
                console.log(res.data.data);
                if (params.isShowSuccessMsg && code === 6666) showToast({ title: msg });
                if (params.isShowErrorMsg && code !== 6666 && msg) showToast({ title: msg });
                if (typeof params.success === 'function') params.success(res.data, sourceData, loginInfoFromResolve)
            },
            complete: res => {
                console.log('------complete------');
                console.log(res);
                const { statusCode } = res;
                deleteRequestList(params.url);
                if (typeof params.complete === 'function') params.complete(res.data, res)
            },
            fail: res => { // invoke this callback as long as fail to set the request, and the res wil be an object which just has only one key 'errMsg', like this { errMsg: 'error message' }, I hope so.
                // {errMsg: "request:fail timeout"}
                console.log('------fail------');
                console.log(params.url);
                console.log(res);
                wx.request({
                    url: requestWrapper.errorCatcherParams.url,
                    data: {
                        data: res,
                        statusCode: res.statusCode,
                        time: new Date().getTime()
                    }
                });
                if (typeof params.fail === 'function') params.fail(res)
            }
        })
    });

}

requestWrapper.defaultParams = {
    isEnCode: true,
    isMergeDefaultData: true,
    isShowSuccessMsg: false,
    isShowErrorMsg: true,
    loading: true,
    isShowingLoading: false,
    method: 'POST',
    header: {
        'content-type': 'application/json'
    }
};

requestWrapper.defaultData = {
    "cversion": CVERSION,
    "channel": CHANNEL
};

requestWrapper.errorCatcherParams = {
    url: 'http://192.168.1.114:3000/errorCatcher'
};

requestWrapper.handleLogTimeout = function () {
    showToast({ title: '登录超时, 正在重新登录' });
    const pages = getCurrentPages();
    const length = pages.length;
    const currentPages = pages[length - 1];
    const currentRoute = '/' + currentPages.route;
    const APP = getApp();
    APP.globalData.loginPromise = new Promise(resolve => {
        wx.login({
            success: res => {
                postLogin(res.code, APP.globalData, resolve);
            }
        });
    });
    APP.globalData.loginPromise.then(() => {
        wx.reLaunch({ url: currentRoute })
    });
};

module.exports = {
    requestWrapper,
    requestList
};